#!/usr/local/bin/python3
# *_* coding: UTF-8 *_*
# @IDE: PyCharm
# @Version: Python3.7
# @Author: Kendrick.Kc
# @Email: 509556985@qq.com
# @File: process.py
# @Inst: 这里是模块名描述
# @Time: 2023/7/22 12:15
# -----


import traceback
import os
import signal
import platform

from basic.models import ProcessNumber
from django.forms.models import model_to_dict
from django.http import JsonResponse
from multiprocessing import Process
from binance_era.settings import Parameter
from binance_era.strategy import ERA
from utils.timestamp import now_time_stamp


class ERAProcessAppStart(Parameter):

    def __init__(self, binance, request_data):
        self.binance = binance  # 实例化接收到的中间接口类
        self.request_data = request_data  # 前端请求过来的data

    def app_start(self):
        """
        策略启动
        :return:
        """

        self.binance.logger_info(f"{self.binance.strategy_name}策略程序启动......")

        if not self.binance.pan_openings["pan"]:    # 实盘
            if self.binance.get_user_position(self.binance.parameter.symbol)["number"] == 0:  # 不存在持仓
                account = self.binance.exchange_available_balance()
                self.set_db_data(account)

        else:       # 模拟盘
            try:
                db_coll = self.binance.cache_get(self.binance.parameter.db_coll) or {}
                if not db_coll:
                    self.set_db_data(self.binance.parameter.set_balance)

                elif db_coll[self.binance.parameter.db_coll] <= db_coll[self.binance.parameter.db_coll_init]:
                    self.set_db_data(self.binance.parameter.set_balance)
            except:
                self.set_db_data(self.binance.parameter.set_balance)

        p = Process(target=ERA, args=(self.binance, ))
        p.start()

        # 保存进程号
        process_obj = ProcessNumber.objects.update_or_create(exchange=self.binance.exchange_name,
                                                             strategy=self.binance.strategy_name,
                                                             defaults={
                                                                 "process": [p.pid],
                                                                 "status": self.request_data["status"],
                                                                 "pan_opening": self.request_data["pan_opening"],
                                                                 "timestamp": now_time_stamp()
                                                             })
        return JsonResponse({'data': model_to_dict(process_obj[0]), 'code': 200, 'msg': 'ok'})

    def position_stop(self):
        """
        平仓停止
        :return:
        """

        try:
            process_obj = ProcessNumber.objects.filter(exchange=self.binance.exchange_name,
                                                       strategy=self.binance.strategy_name).first()
            process_obj.status = self.request_data["status"]
            process_obj.timestamp = now_time_stamp()
            process_obj.save()
            self.binance.cache_set(self.binance.parameter.db_coll_program, True)  # 初始化手动停止程序的数据表
            self.binance.logger_info(f"设置{self.binance.parameter.db_coll_program}缓存数据【平仓停止】完成.")
            return JsonResponse({'data': model_to_dict(process_obj), 'code': 200, 'msg': 'ok'})
        except:
            self.binance.logger_error(f"机器人平仓停止错误: {traceback.format_exc()}")
            return JsonResponse({'code': 31502, 'msg': '机器人平仓停止错误.'})

    def now_stop(self):
        """
        立即停止
        :return:
        """

        try:
            process_obj = ProcessNumber.objects.filter(exchange=self.binance.exchange_name,
                                                       strategy=self.binance.strategy_name).first()
            process_obj.status = self.request_data["status"]
            process_obj.timestamp = now_time_stamp()

            sig = signal.SIGINT if platform.system() == "Windows" else signal.SIGKILL
            try:
                for pid in process_obj.process:
                    os.kill(pid, sig)
            except:
                self.binance.logger_warning(f"kill子进程错误: {traceback.format_exc()}")
            process_obj.process = []
            process_obj.save()

            self.binance.logger_info(f"【立即停止】成功.")
            return JsonResponse({'data': model_to_dict(process_obj), 'code': 200, 'msg': 'ok'})
        except:
            self.binance.logger_error(f"机器人立即停止错误: {traceback.format_exc()}")
            return JsonResponse({'code': 31503, 'msg': '机器人立即停止错误.'})

    def set_db_data(self, account):
        """ 设置本地数据 """
        self.binance.cache_set(self.binance.parameter.db_coll_program, False)  # 重设只平不开数据
        self.binance.cache_set(self.binance.parameter.db_coll_up, [account])    # 记录上一次结算后的账户可用余额
        data = {
            self.binance.parameter.db_coll: account,  # 正在交易的金额
            self.binance.parameter.db_coll_init: account,  # 初始金额
            self.binance.parameter.db_coll_side: None,  # 持仓方向
            self.binance.parameter.db_coll_price: None,  # 开仓价格
            self.binance.parameter.db_coll_pos: 0,  # 仓位数量
            self.binance.parameter.db_coll_timeStamp: now_time_stamp()  # 启动时间
        }
        self.binance.cache_set(self.binance.parameter.db_coll, data)
